package com.colorfruit.admin.outer.weixin;

import com.colorfruit.admin.pojo.constant.CommonConstant;
import com.colorfruit.framework.common.util.CommonUtil;
import com.colorfruit.framework.common.util.Md5Util;
import com.colorfruit.framework.httpclient.HttpClientPool;
import lombok.extern.slf4j.Slf4j;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Slf4j
public class WxUtil {

    /**
     * 微信登录
     *
     * @param code
     * @param appid
     * @return
     */
    public static String wxLogin(String code, String appid) {
        Map<String, String> paramsMap = new HashMap<>();
        paramsMap.put("appid", appid);
        paramsMap.put("secret", CommonConstant.SECRET);
        paramsMap.put("js_code", code);//用户登录凭证
        paramsMap.put("grant_type", CommonConstant.GRANT_TYPE);
        String response = HttpClientPool.getHttpClientPoolInstance().get(CommonConstant.LOGIN_URL, paramsMap, null);
        log.info("wx-login response = {}", response);
        return response;
    }

    /**
     * @param appid            小程序ID
     * @param mch_id           商户号
     * @param description      商品描述
     * @param out_trade_no     商户订单号
     * @param total_fee        标价金额
     * @param spbill_create_ip 终端IP
     * @param notify_url       通知地址
     * @param api_key          API秘钥key
     * @return
     */
    public static Map wxPay(String appid,
                            String mch_id,
                            String description,
                            String out_trade_no,
                            String total_fee,
                            String spbill_create_ip,
                            String notify_url,
                            String api_key,
                            String openid) {
        //1. 生成sign
        Map<String, String> paraMap = new HashMap<>();
        //设置请求参数(小程序ID)
        paraMap.put("appid", appid);
        //设置请求参数(商户号)
        paraMap.put("mch_id", mch_id);
        //设置请求参数(随机字符串)
        paraMap.put("nonce_str", UUID.randomUUID().toString().replace("-",""));
        //设置请求参数(商品描述)
        paraMap.put("body", description);
        //设置请求参数(商户订单号)
        paraMap.put("out_trade_no", out_trade_no);
        //设置请求参数(总金额)
        paraMap.put("total_fee", total_fee);
        //设置请求参数(终端IP)
        paraMap.put("spbill_create_ip", spbill_create_ip);
        //设置请求参数(通知地址)
        paraMap.put("notify_url", notify_url);
        //设置请求参数(交易类型)
        paraMap.put("trade_type", "JSAPI");
        //设置请求参数(openid)(在接口文档中 该参数 是否必填项 但是一定要注意 如果交易类型设置成'JSAPI'则必须传入openid)
        paraMap.put("openid", openid);
        //调用逻辑传入参数按照字段名的 ASCII 码从小到大排序（字典序）
        String stringA = CommonUtil.formatUrlMap(paraMap, false, false);
        log.info("ASCLL排序后的值 = {}", stringA);
        //在stringA最后拼接上key得到stringSignTemp字符串，并对stringSignTemp进行MD5运算，再将得到的字符串所有字符转换为大写，得到sign值signValue。(签名)
        String sign = Md5Util.encryption(stringA + "&key=" + api_key).toUpperCase();

        //2. 将参数 编写XML格式
        StringBuffer paramBuffer = new StringBuffer();
        paramBuffer.append("<xml>");
        paramBuffer.append("<appid>" + appid + "</appid>");
        paramBuffer.append("<mch_id>" + mch_id + "</mch_id>");
        paramBuffer.append("<nonce_str>" + paraMap.get("nonce_str") + "</nonce_str>");
        paramBuffer.append("<sign>" + sign + "</sign>");
        paramBuffer.append("<body>" + description + "</body>");
        paramBuffer.append("<out_trade_no>" + paraMap.get("out_trade_no") + "</out_trade_no>");
        paramBuffer.append("<total_fee>" + paraMap.get("total_fee") + "</total_fee>");
        paramBuffer.append("<spbill_create_ip>" + paraMap.get("spbill_create_ip") + "</spbill_create_ip>");
        paramBuffer.append("<notify_url>" + paraMap.get("notify_url") + "</notify_url>");
        paramBuffer.append("<trade_type>" + paraMap.get("trade_type") + "</trade_type>");
        paramBuffer.append("<openid>" + paraMap.get("openid") + "</openid>");
        paramBuffer.append("</xml>");
        Map<String,Object> responseMap = null;
        try {
            //发送请求(POST)(获得数据包ID)(这有个注意的地方 如果不转码成ISO8859-1则会告诉你body不是UTF8编码 就算你改成UTF8编码也一样不好使 所以修改成ISO8859-1)
            log.info("==========================微信预支付调用开始===paramBuffer = {} ====================================", paramBuffer.toString());
//            String responseXml = HttpClientPool.getHttpClientPoolInstance().get(CommonConstant.WX_PRE_PAY_URL, new String(paramBuffer.toString().getBytes(), "ISO8859-1"));
//            responseMap = CommonUtil.xmlToMap(responseXml);
           responseMap = CommonUtil.xmlToMap(CommonUtil.getRemotePortData(CommonConstant.WX_PRE_PAY_URL, new String(paramBuffer.toString().getBytes(), "ISO8859-1")));
            log.info("==========================微信预支付调用完成==xml={}=map====================================", responseMap);
        } catch (UnsupportedEncodingException e) {
            log.info("微信 统一下单 异常："+e.getMessage());
            e.printStackTrace();
        } catch (Exception e) {
            log.info("微信 统一下单 异常："+e.getMessage());
            e.printStackTrace();
        }
        return responseMap;
    }

    /**
     * 给前端算签名
     * @param appId 小程序ID
     * @param timeStamp 时间
     * @param nonceStr 随机串
     * @param prepay_id 支付ID
     * @param api_key 小程序秘钥
     * @return
     */
    public static String frontSign(String appId,
                                   String timeStamp,
                                   String nonceStr,
                                   String prepay_id,
                                   String api_key){
        Map<String, String> paraMap = new HashMap<>();
        paraMap.put("appId", appId);
        paraMap.put("timeStamp", timeStamp);
        paraMap.put("nonceStr", nonceStr);
        paraMap.put("package", "prepay_id=" + prepay_id);
        paraMap.put("signType", "MD5");
        String stringA = CommonUtil.formatUrlMap(paraMap, false, false);
        log.info("ASCLL排序后的值 = {}", stringA);
        //在stringA最后拼接上key得到stringSignTemp字符串，并对stringSignTemp进行MD5运算，再将得到的字符串所有字符转换为大写，得到sign值signValue。(签名)
        String sign = Md5Util.encryption(stringA + "&key=" + api_key).toUpperCase();
        return sign;
    }

}
